package com.learn.code.juc.forkjoin;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.ForkJoinWorkerThread;
import java.util.concurrent.RecursiveTask;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * @author : 翌擎科技
 * @date : 2022/8/10 16:05
 */
public class SumExecuteCore {

    private static ForkJoinPool forkJoinPool = new ForkJoinPool(50, pool -> {
        final ForkJoinWorkerThread worker = ForkJoinPool.defaultForkJoinWorkerThreadFactory.newThread(pool);
        worker.setName("learn-code-forkJoin-" + worker.getPoolIndex());
        return worker;
    }, (thread, throwable) -> {
        throwable.printStackTrace();
    }, false);

//    private static ForkJoinPool forkJoinPool = new ForkJoinPool(16);


    public static final AtomicInteger taskCount = new AtomicInteger();


    public static Long doAction(int sumBegin, int sumEnd, int threshold) {
        return forkJoinPool.invoke(new SumTask(sumBegin, sumEnd, threshold));
    }

    public static class SumTask extends RecursiveTask<Long> {
        private final int sumBegin;
        private final int sumEnd;
        /**
         * 任务拆分阈值，当任务尺寸大于该值时，进行拆分
         */
        private final int threshold;

        public SumTask(int sumBegin, int sumEnd, int threshold) {
            this.sumBegin = sumBegin;
            this.sumEnd = sumEnd;
            this.threshold = threshold;
        }

        @Override
        protected Long compute() {
            if (sumBegin > sumEnd) {
                return 0L;
            }

            if (sumEnd - sumBegin > threshold) {
//                Collection<SumTask> sumTasks = ForkJoinTask.invokeAll(dividedTasks());

//                List<ForkJoinTask<Long>> joinTasks = ForkJoinTask.invokeAll(dividedTasks()).stream().map(ForkJoinTask::fork).collect(Collectors.toList());
//                return joinTasks.stream().mapToLong(ForkJoinTask::join).sum();
                SumTask taskA = new SumTask(sumBegin, (sumBegin + sumEnd) / 2, threshold);
                SumTask taskB = new SumTask((sumBegin + sumEnd) / 2, sumEnd, threshold);
                taskA.fork();
                taskB.fork();
                taskCount.incrementAndGet();
                return taskA.join() + taskB.join();
            }
            System.out.println(sumBegin+"------"+sumEnd+"---------"+Thread.currentThread().getName());
            //直接执行结果
            long result = 0L;
            for (int i = sumBegin; i < sumEnd; i++) {
                result += i;
            }
            return result;
        }


        private Collection<SumTask> dividedTasks() {
            List<SumTask> sumTasks = new ArrayList<>();
            if (sumEnd - sumBegin <= threshold) {
                sumTasks.add(new SumTask(sumBegin, sumEnd, threshold));
            } else {
                sumTasks.add(new SumTask(sumBegin, (sumBegin + sumEnd) / 2, threshold));
                sumTasks.add(new SumTask((sumBegin + sumEnd) / 2, sumEnd, threshold));
            }
            return sumTasks;
        }
    }
}
